﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace NewKataminoSolver
{
    /// <summary>
    /// The 'BackTracker' abstract class
    /// </summary>
    abstract class BackTracker
    {
        public abstract bool IsSolution();
        public abstract void ProcessSolution();
        public abstract void ProcessCandidate();
        public abstract BackTracker[] Candidates();

        // The "Template method"
        public IEnumerable<BackTracker> Solve()
        {
            Debug.WriteLine("Solve()");
            if (this.IsSolution())
            {
                this.ProcessSolution();
                yield return this;
            }
            BackTracker[] C = Candidates();
            Debug.WriteLine("Candidate list length ' " + C.Length.ToString());
            foreach (BackTracker c in C)
            {
                c.ProcessCandidate();
                foreach (BackTracker s in c.Solve())
                {
                    yield return s;
                }
            }
        }
    }

    class KataminoBackTracker : BackTracker
    {
        // local data
        int _n;
        int[,] data;
        int _W, _H;
        Katamino _k;

        // create initial / empty / partial solution
        public KataminoBackTracker(Katamino k, int w, int h)
        {
            // set and initialize data
            _n = 0;
            _W = w;
            _H = h;
            _k = k;
            data = new int[_W, _H];
        }
        public override bool IsSolution()
        {
            return (_n == 12);
        }
        public override void ProcessCandidate()
        {
            // can be used to process partial, but this is special case!
            _k.Refresh();

        }
        public override void ProcessSolution()
        {
            // can be used to process partial, but this is special case!
            _k.Refresh();

        }
        public override BackTracker[] Candidates()
        {
            BackTracker[] result = {};

            return result;
        }
    }

    /// <summary>
    /// A 'BackTrackerTester' class
    /// </summary>
    class BackTrackerTester : BackTracker
    {
        private int _s;
        private int _v;
        public BackTrackerTester(int s, int v)
        {
            Debug.WriteLine("BackTrackerTester() [creator]: "+ s.ToString() + ", " + v.ToString());
            _s = s;
            _v = v;
        }
        public override bool IsSolution()
        {
            bool result = ((_v % 2) == 1);
            Debug.WriteLine("IsSolution(" + _v.ToString() + ") = " + result.ToString());
            return result;
        }
        public override void ProcessCandidate()
        {
            Debug.WriteLine("ProcessCandidate() : " + _v.ToString());
        }
        public override void ProcessSolution()
        {
            Debug.WriteLine("ProcessSolution() : " + _v.ToString());
        }
        public override BackTracker[] Candidates()
        {
            Debug.WriteLine("Candidates()");
            BackTrackerTester[] r = { new BackTrackerTester(_s + 1, 0), new BackTrackerTester(_s + 1, 1), new BackTrackerTester(_s + 1, 3) };
            BackTrackerTester[] e = { };

            if (_s < 1)
                return r;
            else 
                return e;
        }
    }
}
